home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr48
/
386p_200.zip
/
386FILE.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-01-12
|
13KB
|
447 lines
.386p
code32 segment para public use32
assume cs:code32,ds:code32
include 386power.inc
align byte
; This module uses the space between
; _LoMemBase and lomemtop for buffering file transferts to extended memory
fname_buf db 256 dup(0) ; buffer fo filename
; _FOpen: Opens a file and returns its handle into V86bx
; In:
; ESI -> ASCIIZ filename max. 255 bytes long
; AL == file mode: 00 = Read Only
; 01 = Write Only (create it if it doesn't exist)
; Out:
; if carry set then
; Error opening file
; else
; File opened succesfully
; V86bx = file handle
public _FOpen
_FOpen:
pushad
mov ebp,eax
mov cl,1
mov edi,offset fname_buf
zerother:
lodsb
inc cl ; when 255 is reached, this will be resetted
je topped
stosb
or al,al
jne zerother
topped: mov esi,offset fname_buf
mov byte ptr [edi],0 ;put a NUL for safety
add esi,_Code32Base ; get a linear address
mov ecx,esi
mov V86cx,0 ; clear all file attributes OR access mask
shr esi,4 ; segment into dx
and ecx,0fh ; offset into cx
mov eax,ebp ; get eax back
mov V86ax,3D00h
cmp al,00
je gopenr ; al=00 --> open to read
mov V86ax,3C01h ; else --> open to write
gopenr:
mov V86dx,cx ; send seg:ofs
mov V86ds,si ;
mov al,21h ; select interrupt
call _ExecINT ; go V86
mov ax,V86ax ;
mov V86bx,ax ; copy handle to V86bx
popad
ret
; _FClose Closes file with handle V86bx
; In:
; V86bx = file handle
public _FClose
_FClose:
push eax
mov V86ax,3e00h
mov al,21h
call _ExecINT
pop eax
ret
public _FSeek
; _FSeek Seek position in file
; In:
; V86bx = file handle
; EAX = signed offset to move to
; DL = from: 0-beginning of file, 1-current location, 2-end of file
; Out:
; If carry clear then Seek done
; EAX = new offset from beginning of file
; else EAX trashed
_FSeek:
push edx
mov V86ah,42h
mov V86al,dl
mov V86dx,ax
shr eax,16
mov V86cx,ax
mov al,21h
call _ExecINT
jc fserr
mov ax,V86dx
shl eax,16
mov ax,V86ax
fserr:
pop edx
ret
public _FSize
; _FSize Get size of file
; In:
; V86bx = file handle
; Out:
; if Carry Clear then File exist
; EAX = size of file
; else error, EAX trashed
_FSize: push edx
mov dl,01h ; get current file position
xor eax,eax ;
call _FSeek ;
push eax ; save current file position
mov dl,02 ; seek to end of file
xor eax,eax ;
call _FSeek ;
pop edx ; restore current file position
push eax ; save file lenght
mov eax,edx ; restore file pointer
mov dl,00 ;
call _FSeek ;
pop eax ; restore result
; EAX = FILE SIZE
pop edx
ret
; _FRead Reads a block from a file with handle V86bx
; In: V86bx = file handle
; EDI = base address of block ( relative offset)
; into extended memory
; EAX = size of block
; Out: If carry clear
; N.B. The space between _LoMemBase and _LoMemTop is used as a
; "transition buffer" if EDI points into extended memory
public _FRead
_FRead:
pushad
mov ebp,_LoMemBase
mov edx,eax ; copy into EDX size of block to read
mov ebx,_LoMemTop ;
cmp edi,ebp ;
jb @nouppa ; low memory destination, write directly to it
; high memory destination, use low memory as a buffer
mov ecx,0FFE0h ; make sure we don't have false wraps
sub ebx,_LoMemBase ;
and bl,cl ; get free low memory (paragraph aligned)
cmp ebx,ecx
jb @rsmall
mov ebx,ecx ; read 0FFF0 bytes a time
@rsmall: ; ebx = size of buffer in low memory
add ebp,_Code32Base ; convert to linear address
@rchunk:
cmp ebx,edx
jb @rfittrans ; if (bytes_to_read > buffer) then read another chunk
mov ebx,edx ; else this is the last chunk, make it fit
@rfittrans: ; ebx = size of chunk to read
mov esi,ebp ; convert linear address to seg:ofs
mov ecx,ebp ;
shr esi,4 ;
and ecx,0Fh ;
mov V86ds,si ;
mov V86dx,cx ;
mov V86cx,bx ; chunk size
mov V86ah,3fh ; read chunk
mov al,21h ;
call _ExecINT ;
jc @rfloaderr ; get out if error
mov esi,_LoMemBase ;
mov ecx,ebx ; move up this chunk
rep movsb ;
sub edx,ebx ; update counter of bytes to read
jne @rchunk ; end of block ? if not at the end, read next chunk
clc ; say, no error
@rfloaderr:
popad
ret
@rflucked:
stc ; say, error
popad
ret
@nouppa: ; load into low memory
mov edx,eax
mov ebx,0FFF0h
; get linear address
mov ebp,edi
add ebp,_Code32Base
@lrchunk:
cmp ebx,edx
jbe @lrfittrans ; if (bytes_to_read > buffer) then read another chunk
mov ebx,edx ; else this is the last chunk, make it fit
@lrfittrans: ; ebx = size of chunk to read
mov esi,ebp ; convert linear address to seg:ofs
mov ecx,ebp ;
shr esi,4 ;
mov V86ds,si ;
and ecx,0Fh ;
mov V86dx,cx ;
mov V86cx,bx ; chunk size
mov V86ah,3fh ; read chunk
mov al,21h ;
call _ExecINT ;
jc @lrfloaderr ; get out if error
add ebp,ebx ; move forward the linear pointer
sub edx,ebx ; update counter of bytes to read
jne @lrchunk ; end of block ? if not at the end, read next chunk
clc ; say, no error
@lrfloaderr:
popad
ret
; standard 386file error messages
eropen db 'ERROR WHILE OPENING FILE TO READ FROM',CR,LF,CR,LF,'$'
ewopen db 'ERROR WHILE OPENING FILE TO WRITE TO',CR,LF,CR,LF,'$'
eracc db 'ERROR WHILE READING FROM FILE',CR,LF,CR,LF,'$'
ewacc db 'ERROR WHILE WRITING TO FILE',CR,LF,CR,LF,'$'
; _FLoad Loads a file with ASCIIZ name pointed by DS:ESI (max 255 bytes)
; Out: If carry clear
; EAX = file size
; The file gets loaded starting from _HiMemBase
; The space between _LoMemBase and _LoMemTop is used as a
; "transition buffer"
; N.B. _LoMemBase and _HiMemBase are left as they were
; BEFORE calling _FLoad, what will you do with the heaps
; is up to you ( you can update them using the file size
; or simply do nothing and "discard" the loaded data ).
; Why use extended mem instead of dos mem ? Because dos mem
; is precious, it's the only place where you can put things directly
; accessible in 'real' and protected mode.
public _FLoad
_FLoad: ; ds:esi = ptr to ASCIIZ file name
push edi
push ebp
mov al,0 ; read from file
mov _386Return,offset eropen
call _FOpen
jc @flucked ; Oops! Cannot open file
call _FSize
jc @flucked ; Oops! Seek problems
mov _386Return,offset eracc
mov edi,_HiMemBase ; Is there enough free space in high memory ?
mov ebp,_HiMemTop ;
sub ebp,edi ;
cmp eax,ebp ;
jnbe @flucked ; Oops! File too big
call _FRead
jc @floaderr
mov _386Return, offset _386Terminator
call _FClose ; hasta la vista, baby
clc
@floaderr:
pop ebp
pop edi
ret
@flucked:
pop ebp
pop edi
stc
ret
; _LoFLoad
; Loads a file with ASCIIZ name pointed by DS:ESI (max 255 bytes)
; Out: If carry clear
; EAX = file size
; The file gets loaded starting from _LoMemBase
; Use this to directly load things into dos memory
public _LoFLoad
_LoFLoad: ; ds:esi = ptr to ASCIIZ file name
push edi
push ebp
mov _386Return,offset eropen
mov al,0 ; read from file
call _FOpen
jc @flucked ; Oops! Cannot open file
call _FSize
jc @flucked ; Oops! Seek problems
mov _386Return,offset eracc
mov edi,_LoMemBase
mov ebp,_LoMemTop
sub ebp,edi
cmp eax,ebp
ja @flucked ; Oops! File too big
call _FRead
jc @lfloaderr
mov _386Return,offset _386Terminator
call _FClose ; hasta la vista, baby
clc
@lfloaderr:
pop ebp
pop edi
ret
; _FWrite Writes a block of memory to file with handle V86bx
; In: V86bx = file handle
; esi = buffer base (relative address)
; eax = file size
; Out: If carry clear
; file write done
public _FWrite
_FWrite:
pushad
mov edx,eax ; edx = counter of bytes to move
mov ebp,(640*1024) ;
sub ebp,_Code32Base ; code32-relative offset of top 640k
cmp esi,ebp ; is source block under the 640k dos limit ?
jb @writedirect
mov ebp,_LoMemBase
mov ecx,0FFF0h ;max. transfert buffer (paragraph aligned)
mov ebx,_LoMemTop ;
sub ebx,ebp ; available low memory
and bl,cl ; paragraph align
cmp ebx,ecx ; put into ebx the smallest
jb @wfull ;
mov ebx,ecx ;
@wfull: ; ebx = size of transfert buffer
add ebp,_Code32Base ; LINEAR address of _LoMemBase
@wchunk:
cmp ebx,edx ;
jbe @wafittrans ;
mov ebx,edx ; if this is the last chunk, make it fit
@wafittrans: ; ebx = bytes to move this time
mov edi,_LoMemBase ;
mov ecx,ebx ;
rep movsb ; move DOWN TO LOW DOS MEMORY a chunk
mov edi,ebp ; linear to seg:ofs
mov ecx,ebp ;
shr edi,4 ;
mov V86ds,di ;
and ecx,0Fh ;
mov V86dx,cx ;
mov V86cx,bx ;
mov V86ah,40h ;
mov al,21h ; translate & write block
call _ExecINT ;
jc @wfsaverr
sub edx,ebx ;
jne @wchunk ; loop if there are other blocks
popad
clc
ret
@wfsaverr:
popad
stc
ret
@writedirect:
mov edx,eax
; edx = size of block
mov ebx,0FFF0h
; ebx = size of transfert buffer
mov ebp,esi ; LINEAR address of esi
add ebp,_Code32Base
@lwchunk:
cmp ebx,edx ;
jbe @lwafittrans ;
mov ebx,edx ; if this is the last chunk, make it fit
@lwafittrans: ; ebx = bytes to move this time
mov edi,ebp ; linear to seg:ofs
mov ecx,ebp ;
shr edi,4 ;
mov V86ds,di ;
and ecx,0Fh ;
mov V86dx,cx ;
mov V86cx,bx ;
mov V86ah,40h ;
mov al,21h ; translate & write block
call _ExecINT ;
jc @wfsaverr
add ebp,ebx ;
sub edx,ebx ;
jne @lwchunk ; loop if there are other blocks
popad
clc
ret
; _FSave Saves a block of memory
; into the file with ASCIIZ name
; In:
; esi = ptr to asciiz file name in low memory
; edi = buffer base
; eax = file size
; Out: If carry clear
; file write done
public _FSave
_FSave:
push esi
push eax
mov _386Return,offset ewopen
mov al,1
call _FOpen
jc @fsaverr
mov _386Return,offset ewacc
mov eax,[esp]; restore block size into eax
mov esi,edi
call _FWrite
jc @fsaverr
call _FClose
mov _386Return,offset _386Terminator
clc
@fsaverr:
pop eax
pop esi
ret
code32 ends
end